using TUnit.Core.SourceGenerator.Tests.Options;

namespace TUnit.Core.SourceGenerator.Tests;

/// <summary>
/// Tests for the GenericTypeResolver functionality in the unified source generator
/// </summary>
internal class GenericTypeResolverTests : TestsBase<Generators.TestMetadataGenerator>
{
    [Test]
    public async Task Test_GenericTestClass_WithExplicitInstantiation()
    {
        var source = """
        using TUnit.Core;

        namespace TUnit.TestProject;

        [GenerateGenericTest(typeof(int))]
        [GenerateGenericTest(typeof(string))]
        public class GenericTestClass<T>
        {
            [Test]
            public void TestMethod()
            {
                // Test implementation
            }
        }
        """;

        await RunTestWithInlineSource(source);
    }

    [Test]
    public async Task Test_GenericTestMethod_WithExplicitInstantiation()
    {
        var source = """
        using TUnit.Core;

        namespace TUnit.TestProject;

        public class TestClass
        {
            [GenerateGenericTest(typeof(int))]
            [GenerateGenericTest(typeof(string))]
            [Test]
            public void GenericTestMethod<T>()
            {
                // Test implementation
            }
        }
        """;

        await RunTestWithInlineSource(source);
    }

    [Test]
    public async Task Test_EmptyGenericRegistry_WhenNoGenericsFound()
    {
        var source = """
        using TUnit.Core;

        namespace TUnit.TestProject;

        public class SimpleTestClass
        {
            [Test]
            public void NonGenericTest()
            {
                // Test implementation
            }
        }
        """;

        await RunTestWithInlineSource(source);
    }

    [Test]
    public async Task Test_MultipleGenericParameters()
    {
        var source = """
        using TUnit.Core;

        namespace TUnit.TestProject;

        [GenerateGenericTest(typeof(int), typeof(string))]
        [GenerateGenericTest(typeof(bool), typeof(double))]
        public class MultiGenericTestClass<T1, T2>
        {
            [Test]
            public void TestMethod()
            {
                // Test implementation with T1 and T2
            }
        }
        """;

        await RunTestWithInlineSource(source);
    }

    [Test]
    public async Task Test_GenericConstraints_WithInstantiation()
    {
        var source = """
        using TUnit.Core;

        namespace TUnit.TestProject;

        [GenerateGenericTest(typeof(string))]
        [GenerateGenericTest(typeof(object))]
        public class ConstrainedGenericTestClass<T>
            where T : class, new()
        {
            [Test]
            public void TestMethod()
            {
                var instance = new T();
            }
        }
        """;

        await RunTestWithInlineSource(source);
    }

    [Test]
    public async Task Test_NestedGenericTypes()
    {
        var source = """
        using TUnit.Core;
        using System.Collections.Generic;

        namespace TUnit.TestProject;

        [GenerateGenericTest(typeof(List<int>))]
        [GenerateGenericTest(typeof(Dictionary<string, int>))]
        public class NestedGenericTestClass<T>
        {
            [Test]
            public void TestMethod()
            {
                // Test with nested generic type T
            }
        }
        """;

        await RunTestWithInlineSource(source);
    }

    private async Task RunTestWithInlineSource(string source)
    {
        var tempFile = Path.GetTempFileName() + ".cs";
        await File.WriteAllTextAsync(tempFile, source);

        try
        {
            await RunTest(tempFile, new RunTestOptions(), async generatedFiles =>
            {
                // Basic assertion to verify the generator produces output
                await Assert.That(generatedFiles.Length).IsGreaterThan(0);

                // Verify at least one file contains generated content
                var hasGeneratedContent = generatedFiles.Any(f => f.Contains("// <auto-generated/>"));
                await Assert.That(hasGeneratedContent).IsTrue();
            });
        }
        finally
        {
            if (File.Exists(tempFile))
            {
                File.Delete(tempFile);
            }
        }
    }
}
